-module(edbc).

-export([connect/1, 
	close/1, 
	execute/3, 
	execute_fold/5, 
	prepare/3, 
	transaction/2, 
	backend/3,
	behaviour_info/1]).


%% Connect to a database.
%% Options: a proplist with values the backend needs to set up a connection.
%% Returns {ok, Db} or {error, Reason}
%%
connect(Options) ->
	case proplists:lookup(backend, Options) of
		{backend, Mod} ->
			{ok, Opaque} = Mod:connect(Options),
			Db = {edbc, Mod, Opaque},
			{ok, Db};
		none ->
			{error, "No backend specified"}	
	end.

%% Disconnect and let free any resources associated with the db handle.
%% Db: Handle to database, fully opaque.
close(Db={edbc, Mod, _}) ->
	Mod:close(Db).

%% Execute a query on the database, supply values for unbound parameters
%% through Bindings.
%% Db: Database handle
%% Query: SQL statement in a string OR atom naming predefined statement.
%% Bindings: List of values for unbound parameters in the Query.
execute(Db={edbc, Mod, _}, Query, Bindings) ->
	Mod:execute(Db, Query, Bindings).	

%% Same as execute, except results are folded over. Use this if returning
%% large results from 'execute' is a problem.
%% FoldFun: A two-arg function for result folding
%% Acc0: Initial argument to FoldFun.
execute_fold(Db={edbc, Mod, _}, Query, Bindings, FoldFun, Acc0) ->
	Mod:execute_fold(Db, Query, Bindings, FoldFun, Acc0).	

%% Name a given query. Allows clearer code where queries have names 
%% indicating intention rather than contain SQL implementation.
%% Also better possibility for databases to prepare query planning
%% if useful.
prepare(Db={edbc, Mod, _}, Name, Query) ->
	Mod:prepare(Db, Name, Query).

%% Execution a one-arg function in an SQL transaction. Making sure the
%% function call will not return without the SQL transaction having been 
%% ended.
transaction(Db={edbc, Mod, _}, Fun) ->
	Mod:transaction(Db, Fun).

%%
%% Access features exposed by the edbc backend in use.
%% Catch nodef errors and return a friendly error message?
%%
%% Option: symbol name for option
%% Args: List of arguments
backend(Db={edbc, Mod, _}, Option, Args) ->
	apply(Mod, Option, [Db|Args]).
	
behaviour_info(callbacks) ->
	[{connect, 1}, 
	 {close, 1}, 
	 {execute, 3}, 
	 {execute_fold, 5}, 
	 {prepare, 3}, 
	 {transaction, 2}]. 

